Skip to content

feat(edge): detect + speak WHOOP 5 (gen5) alongside WHOOP 4 - #97

Open
abdulsaheel wants to merge 12 commits into
mainfrom
feat/multiband-whoop5
Open

feat(edge): detect + speak WHOOP 5 (gen5) alongside WHOOP 4#97
abdulsaheel wants to merge 12 commits into
mainfrom
feat/multiband-whoop5

Conversation

@abdulsaheel

@abdulsaheel abdulsaheel commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Teaches the BLE engine to detect and talk to WHOOP 5 (gen5 / "fd4b") bands as well as WHOOP 4. Pairs with OpenStrap/protocol#16 (the BandProfile abstraction). Analytics needs no changes — WHOOP 5 just feeds the same decoded_onehz/decoded_rr tables.

Changes (all in lib/ble/ble_engine.dart)

  • Scan filters both service UUIDs (gen4 6108xxxx / gen5 fd4bxxxx).
  • Discovery pins the generation per session (_Session.applyBand) and rebuilds the frame reassemblers with the matching header shape; characteristics resolved via the generation's GATT prefixes.
  • BandProfile threaded through the frame path, the command builder (_send), and the history-result ACK (safe-trim token echo).
  • Gen5 handshake branch in sendInit: client-hello (0x91) + empty-payload GET_DATA_RANGE/SEND_HISTORICAL_DATA.
  • Record ingest routes gen5 through parseGen5Record; unknown/motion kinds fall through to raw_archive as before.

Testing

  • flutter test --concurrency=1483 pass (no regression).
  • flutter analyze lib/ble/ → clean.

Invariants preserved

  • The WHOOP 4 path is byte-identical (gen4 is the default profile).
  • Safe-trim ACK invariant unchanged: durable commit still precedes the (now band-correct) ACK token echo.
  • Live high-rate streams still never persisted; decoded_* schema unchanged.

⚠️ Known limitation

The gen5 connect/handshake path is not yet validated on physical hardware (no WHOOP 5 band available) — clearly marked in-code. Decode is validated against real owned captures + synthetic vectors. Requires an on-device pairing pass (bond → handshake → offload → ACK → trim → decode → day derive) before shipping to gen5 users.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added multi-generation WHOOP support, including Gen 5 device pairing and selection on iOS.
    • Added Gen 5 historical data support for heart rate, RR intervals, and gravity data.
    • Added optional Gen 5 deep-buffer downloads.
    • Added generation-aware hello, haptic, clock, and data-transfer commands.
  • Bug Fixes
    • Improved Bluetooth discovery, session setup, framing, acknowledgments, and historical transfers across generations.
    • Added safeguards against destructive commands and improved diagnostic clock handling.
  • Chores
    • Updated the protocol integration for experimental WHOOP 5 support.

Scan filters both service UUIDs (gen4 6108xxxx / gen5 fd4bxxxx); at
discovery the session pins its generation and rebuilds the frame
reassemblers with the matching header shape. The BandProfile is threaded
through the frame path, the command builder, and the history-result ACK
(the safe-trim token echo). Adds the gen5 handshake branch (client-hello
+ empty-payload offload) and routes gen5 records through parseGen5Record;
unknown/motion kinds fall through to raw_archive as before.

The WHOOP 4 path is unchanged. The gen5 connect/handshake path is not yet
validated on physical hardware (marked in-code) — pending a WHOOP 5 band.
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

BLE scanning, service discovery, protocol handling, initialization, historical decoding, diagnostics, and iOS accessory selection now support WHOOP gen4 and gen5 bands through generation-specific profiles, commands, UUIDs, and transfer flows.

Changes

WHOOP generation support

Layer / File(s) Summary
Session generation detection
lib/ble/ble_engine.dart, lib/data/models.dart
Scanning and discovery identify gen4 or gen5 services, apply the matching BandProfile, rebuild frame reassemblers, and record the generation in DeviceState.
Generation-aware protocol and history handling
lib/ble/ble_engine.dart, test/gen5_sample_mapping_test.dart
Command framing, safety checks, offload payloads, acknowledgements, historical decoding, ledger metadata, and gen5 sample mapping use generation-specific behavior.
Generation-specific initialization and controls
lib/ble/ble_engine.dart
Gen5 connections use client hello, optional R22 deep-buffer activation, generation-specific clock and haptic commands, and empty-payload historical transfer. Gen4 retains its existing flow.
Gen5 diagnostics and clock correlation
lib/ble/ble_engine.dart
Gen5 hello and console responses are logged, and clock responses expose plausible Unix timestamps as clock_epoch.
iOS accessory selection and protocol configuration
ios/Runner/AccessorySetup.swift, ios/Runner/Info.plist, pubspec.yaml
iOS setup exposes both WHOOP service UUIDs and picker entries. Bluetooth configuration includes the gen5 service. The protocol dependency points to the WHOOP 5 multi-band branch.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BLEScanner
  participant ServiceDiscovery
  participant BLESession
  participant WHOOPBand
  participant HistoricalDecoder
  BLEScanner->>ServiceDiscovery: discover gen4 or gen5 WHOOP services
  ServiceDiscovery->>BLESession: applyBand(BandProfile)
  BLESession->>BLESession: rebuild frame reassemblers
  BLESession->>WHOOPBand: send generation-specific initialization
  BLESession->>WHOOPBand: request generation-specific historical data
  WHOOPBand-->>BLESession: return framed historical records
  BLESession->>HistoricalDecoder: decode records using pinned profile
  HistoricalDecoder-->>BLESession: return supported Sample records
Loading

Possibly related PRs

  • OpenStrap/edge#169: Both changes repin the openstrap_protocol dependency in pubspec.yaml.

Suggested labels: Review effort 5/5

Suggested reviewers: dannymcc

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding WHOOP 5 detection and communication alongside WHOOP 4.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/ble/ble_engine.dart`:
- Around line 2380-2394: Centralize the generation-specific GET_DATA_RANGE and
SEND_HISTORICAL_DATA writes in a helper, using empty gen5 payloads and the
existing gen4 payloads as appropriate. Update the gen5 initial flow near
gen5ClientHello() and _startHistoricalRefresh() to call this helper so periodic,
manual, and retry refreshes preserve the gen5 command format.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fd244272-7c1d-4b50-b23c-9dbae531602f

📥 Commits

Reviewing files that changed from the base of the PR and between e85345f and 7bbbe8c.

📒 Files selected for processing (1)
  • lib/ble/ble_engine.dart

Comment thread lib/ble/ble_engine.dart
…paths

CodeRabbit review: the initial handshake used gen5 empty-payload
GET_DATA_RANGE/SEND_HISTORICAL_DATA, but the periodic backfill, manual
refresh, and retry paths still sent the gen4 [0x00] payload (only the
frame envelope was band-correct). Extract _sendGetDataRange /
_sendHistoricalData helpers that pick the payload by generation (gen4
[0x00], gen5 empty) and route the init, refresh, backfill, and retry
paths through them, so the gen5 offload format is identical everywhere.
@abdulsaheel

Copy link
Copy Markdown
Collaborator Author

Addressed in 67fa1cb — extracted _sendGetDataRange/_sendHistoricalData helpers that pick the payload by generation (gen4 [0x00], gen5 empty) and routed the init handshake, periodic backfill, manual refresh, and retry paths through them, so the gen5 offload command format is now identical everywhere. flutter analyze clean, 483 tests still green.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

@abdulsaheel I’ll review the updated helper routing and generation-specific offload command handling. 🐇

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…t gen5 branch

The BLE engine could speak gen5, but a WHOOP 5 band could not be paired
on iOS: AccessorySetupKit only advertised the gen4 6108 service, so a
fd4b band never appeared in the picker (and with no ASK provisioning the
restore central is never created → no connection at all).

- AccessorySetup.swift: offer one ASPickerDisplayItem per generation
  (gen4 6108 + gen5 fd4b) so either band can be provisioned; the
  provisioned CoreBluetooth identifier is generation-agnostic.
- Info.plist: add the gen5 service to NSAccessorySetupBluetoothServices
  (required for the descriptor criterion).
- pubspec.yaml: point openstrap_protocol at feat/multiband-whoop5 for the
  experimental build (revert to main once protocol#16 merges).

Android needs no change: CDM associates by MAC (generation-agnostic) and
the Flutter scan is already fd4b-aware. iOS restore reconnects by
peripheral identifier, also generation-agnostic.

Still hardware-unvalidated end-to-end — pending a physical WHOOP 5 band.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pubspec.yaml (1)

27-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Branch ref makes builds non-reproducible; pin a commit for release.

Using ref: feat/multiband-whoop5 means a force-push to that branch silently changes the resolved dependency, making builds non-reproducible. This is acceptable for experimental development, but before any release or merge to a production branch, pin to a specific commit SHA instead of a branch ref.

🔒️ Suggested pinning for reproducibility
   openstrap_protocol:
     git:
       url: https://github.com/OpenStrap/protocol.git
-      # EXPERIMENTAL: WHOOP 5 (gen5) multi-band support. Point back to `main`
-      # once OpenStrap/protocol#16 merges.
-      ref: feat/multiband-whoop5
+      # EXPERIMENTAL: WHOOP 5 (gen5) multi-band support. Point back to `main`
+      # once OpenStrap/protocol#16 merges.
+      # Pinned to a specific commit for reproducibility; update intentionally.
+      ref: <commit-sha-of-branch-tip>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pubspec.yaml` around lines 27 - 29, Replace the branch-based ref for the
OpenStrap dependency in the WHOOP 5 experimental configuration with the specific
reviewed commit SHA before release or production-branch merge. Keep the
dependency source and existing experimental intent unchanged, and remove the
non-reproducible feat/multiband-whoop5 branch reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pubspec.yaml`:
- Around line 27-29: Replace the branch-based ref for the OpenStrap dependency
in the WHOOP 5 experimental configuration with the specific reviewed commit SHA
before release or production-branch merge. Keep the dependency source and
existing experimental intent unchanged, and remove the non-reproducible
feat/multiband-whoop5 branch reference.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0bd7319d-ad6c-41b3-85ec-f7333f0d0e93

📥 Commits

Reviewing files that changed from the base of the PR and between 67fa1cb and 360ea72.

📒 Files selected for processing (3)
  • ios/Runner/AccessorySetup.swift
  • ios/Runner/Info.plist
  • pubspec.yaml

Pin the committed lock's openstrap_protocol dependency to the gen5 branch
commit (687aa46) so CI/release resolves the exact experimental protocol
revision. Only the protocol ref/resolved-ref changed; analytics stays on
main. (Locally the gitignored pubspec_overrides.yaml still redirects to
../protocol for dev; the committed lock is what release resolution uses.)
@Aurelian-Shuttleworth

Copy link
Copy Markdown

I have a whoop 5 that I am willing to use to validate against if that would help?

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 82b094c)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Sequence Number Desync

Calling _seq.nextLive() only once for buildR22EnableSequence desyncs the sequence allocator if the builder generates multiple frames. The builder will consume startSeq, startSeq+1, etc., but _seq only advances by 1. The next command sent via _send (e.g., _sendGetDataRange right after this) will reuse a sequence number already consumed by the R22 sequence, causing the band to drop the command or disconnect. You must advance _seq by frames.length - 1 to burn the consumed sequence numbers.

final frames = buildR22EnableSequence(startSeq: _seq.nextLive());

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

…ted engine

Extends BleEngine (not a parallel copy) so a gen5 link gets a real,
working lifecycle end to end instead of stopping at "connected":

- SET_CLOCK/GET_CLOCK now use gen5's own opcodes (SET_CLOCK_MAVERICK/
  GET_CLOCK_GEN5) instead of silently sending gen4's — the bug that would
  have left a gen5 strap's RTC forever unlatched and refusing history.
- Historical-record ingestion now calls protocol's real parseGen5Historical
  (v18/v20/v21/v26) via a new sampleFromGen5Historical mapper, replacing the
  old parseGen5Record call that targeted gen4's version numbers and would
  have silently archived every real gen5 record.
- Added the opt-in R22 deep-buffer enable sequence (default OFF, gated by
  a constructor toggle) and a gen5 Maverick haptic buzz path.
- _send now also blocks OpcodeSafety.destructive band-agnostically,
  alongside the existing gen4 dangerousCmds list.
- decodeFrame is now called with the session's BandProfile so gen5's
  direct-percent battery / GET_HELLO shape decode correctly; added a small
  edge-side augment for GET_CLOCK_GEN5's clock_epoch (protocol doesn't
  populate it yet) and debug-only logging for gen5 console/hello frames.
- DeviceState.generation + a band_generation ledger field surface which
  WHOOP generation a session/batch came from, with no schema migration
  (rides the existing sync_ledger meta_json blob).
- New gen5_sample_mapping_test.dart covers the v18->Sample mapping against
  a real byte-verified capture, plus the deep-buffer/null fall-through.

gen4 behavior is unchanged (every branch above is band-gated); full suite
green (1059 tests, 2 pre-existing skips). Real-hardware validation of the
handshake and R22 sequence is still outstanding — see inline doc comments.
The previous pin (7f1a2db) predates protocol's real v18/v20/v21/v26
decoders, gen5 clock/haptics/SET_CONFIG opcodes, R22 sequence builder,
OpcodeSafety gate, and CONSOLE_LOGS decoder — all of which the previous
edge commit's BleEngine changes call directly. Verified with a clean
`flutter pub get` (no local path override) against this SHA: analyze and
the full test suite (1059 tests) both green.
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 9d13f1b

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit aa18782

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/ble/ble_engine.dart (2)

970-992: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use GattProfile prefixes instead of hardcoded magic strings for scan matching.

The scan callback hardcodes '61080001' and 'fd4b0001' as service-UUID prefixes. Service discovery at Line 1173 and Line 1178 uses GattProfile.gen4.servicePrefix and GattProfile.gen5.servicePrefix for the same purpose. Two sources of truth exist for identical values. If either prefix constant changes, the scan's early-stop optimization silently desyncs from the actual discovery match, and the scan runs to its full timeout instead of stopping early.

Reference the same constants in both places.

♻️ Proposed fix
         if (found == null &&
             (name.contains('whoop') ||
                 advNames.any((s) =>
-                    s.startsWith('61080001') || s.startsWith('fd4b0001')))) {
+                    s.startsWith(GattProfile.gen4.servicePrefix.toLowerCase()) ||
+                    s.startsWith(GattProfile.gen5.servicePrefix.toLowerCase())))) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/ble/ble_engine.dart` around lines 970 - 992, Update the scan callback in
the BLE discovery flow to replace the hardcoded “61080001” and “fd4b0001” checks
with GattProfile.gen4.servicePrefix and GattProfile.gen5.servicePrefix, matching
the constants used by service discovery. Keep the existing case-normalized
prefix matching and early-stop behavior unchanged.

1426-1426: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add regression coverage for the gen5 refresh offload payload.

lib/ble/ble_engine.dart sends [0x00] for gen4 and [] for gen5, but the test suite only exercises gen5 historical mapping through test/gen5_sample_mapping_test.dart. Add a gen5-pinned refresh/backfill/retry regression that asserts GET_DATA_RANGE / SEND_HISTORICAL_DATA are sent with an empty payload, not only the initial sendInit path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/ble/ble_engine.dart` at line 1426, Add regression coverage in the gen5
refresh/backfill/retry test flow around _sendGetDataRange, pinning the device
generation to gen5 and asserting GET_DATA_RANGE and SEND_HISTORICAL_DATA use
empty payloads. Exercise the refresh path beyond the initial sendInit sequence,
including backfill and retry behavior, while preserving the existing gen4
payload expectations.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pubspec.yaml`:
- Around line 38-44: Update the stale protocol-generation comments near the
WHOOP dependency to describe the active experimental WHOOP 5 multi-band
configuration and pinned protocol commit, removing any WHOOP-4-only or ref: main
claims. Keep the dependency pinned to the existing full commit SHA and do not
introduce a branch reference.
- Around line 38-44: Before release, validate the pinned experimental protocol
from the WHOOP 5 flow through gen5 connection, handshake, and R22 behavior on
physical hardware, including GATT discovery and device-specific framing; update
the release readiness or dependency decision around the pubspec ref only after
those checks pass.
- Around line 38-44: The protocol dependency pin in the pubspec must reference a
commit that actually contains the claimed gen5 framing and CRC implementation
changes. Update the ref under the WHOOP 5 multi-band dependency comments to the
correct SHA containing the crc8 length-field validation, odd-length hex
rejection, and profile-aware header-CRC fixes; preserve the pinned-commit
approach.

---

Outside diff comments:
In `@lib/ble/ble_engine.dart`:
- Around line 970-992: Update the scan callback in the BLE discovery flow to
replace the hardcoded “61080001” and “fd4b0001” checks with
GattProfile.gen4.servicePrefix and GattProfile.gen5.servicePrefix, matching the
constants used by service discovery. Keep the existing case-normalized prefix
matching and early-stop behavior unchanged.
- Line 1426: Add regression coverage in the gen5 refresh/backfill/retry test
flow around _sendGetDataRange, pinning the device generation to gen5 and
asserting GET_DATA_RANGE and SEND_HISTORICAL_DATA use empty payloads. Exercise
the refresh path beyond the initial sendInit sequence, including backfill and
retry behavior, while preserving the existing gen4 payload expectations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 118d5963-8206-46f1-8518-4e8f4e54f1af

📥 Commits

Reviewing files that changed from the base of the PR and between 360ea72 and 9d13f1b.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • ios/Runner/Info.plist
  • lib/ble/ble_engine.dart
  • lib/data/models.dart
  • pubspec.yaml
  • test/gen5_sample_mapping_test.dart

Comment thread pubspec.yaml Outdated
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

1 similar comment
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit e21bbaf

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 260cd0c

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 63a87ed

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 82b094c

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

@majidtahir1

Copy link
Copy Markdown

I was able to connect with my whoop 5. so far i can see heart rate data live. I will keep it connected to see recovery/strain and other data points.

@abdulsaheel

Copy link
Copy Markdown
Collaborator Author

I was able to connect with my whoop 5. so far i can see heart rate data live. I will keep it connected to see recovery/strain and other data points.

Great !! Thanks, lets continue this discussion here: #178

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants